#define __GAME_CPP__

#include "Game.h"

//X Y棋子位置
static int X[2];
static int Y[2];

//棋子数量
static int Count = 0;

AI* ai = nullptr;

void Menu(void)
{
    printf("\e[1;1H\e[2J");
    printf("##################################\n");
    printf("##################################\n");
    printf("#####   1.PLAY      0.EXIT   #####\n");
    printf("##################################\n");
    printf("##################################\n");
    printf("Please Select# ");
}

static void ShowBoard(int board[ROW][COL], int row, int col)
{
    printf("\e[1;1H\e[2J");
    printf("   ");
    for (int i = 1; i <= row; i++)
        printf("%3d", i);
    printf("\n");
    for (int i = 0; i < row; i++)
    {
        printf("%3d ", i + 1);
        for (int j = 0; j < col; j++)
        {
            switch (board[i][j])
            {
                case EMPTY :
                    printf(" . ");
                    break;
                case PLAYER1 : 
                    printf(" ● ");
                    break;
                case PLAYER2 :
                    printf(" ❍ ");
                    break;
                default :
                    break;
            }
        }
        printf("\n");
    }
    printf("player1: ");
    printf(" ● ");
    printf("\t");
    printf("player2: ");
    printf(" ❍ ");
    printf("\n");
}

static void InitBoard(int board[ROW][COL], int row, int col)
{
    X[0] = 0, Y[0] = 0;
    X[1] = 0, Y[1] = 0;
    Count = 0;
    memset(board, 0, sizeof(int) * (row * col));
    ShowBoard(board, row, col);
}

static int PlayerMove(int board[ROW][COL], int row, int col, int player)
{
    while (player == PLAYER1 || ai == nullptr)
    {
        printf("Regret move Please Enter -1 -1\n");
        printf("Player[%d] Please Enter Your Pos# ", player);
        int x = 0, y = 0;
        scanf("%d %d", &x, &y);
        if (x == -1 && y == -1)
        {
            if (X[player - 1] != 0 && Y[player - 1] != 0 && board[X[player - 1] - 1][Y[player - 1] - 1] != EMPTY)
            {
                printf("Regret move success\n");
                board[X[0] - 1][Y[0] - 1] = EMPTY;
                board[X[1] - 1][Y[1] - 1] = EMPTY;
                Count -= 2;
                return player - 1;
            }
            else
            {
                printf("Don't allow regret move\n");
                continue;
            }
        }
        if ((x < 1 || x > row) || (y < 1 || y > col))
        {
            printf("Pos Is Not Right! Try Again\n");
            continue;
        }
        else if (board[x - 1][y - 1] != EMPTY)
        {
            printf("Pos Is Occupied! Try Again\n");
            continue;
        }
        else
        {
            board[x - 1][y - 1] = player;
            X[player - 1] = x, Y[player - 1] = y;
            break;
        }
    }

    if (ai != nullptr && player == PLAYER2)
    {
        printf("Regret move Please Enter -1 -1\n");
        printf("Player[%d] Please Enter Your Pos# ", player);
        AI::XY tmp = ai->AIMove(board, row, col);
        printf("%d %d\n", tmp.x, tmp.y);
        usleep(1500000);
        board[tmp.x - 1][tmp.y - 1] = PLAYER2;
        X[player - 1] = tmp.x;
        Y[player - 1] = tmp.y;
    }
    Count++;
    return player;
}

static int ChessCount(int board[ROW][COL], int row, int col, enum Dir dir, int player)
{
    int count = 0;
    int _x = X[player - 1] - 1;
    int _y = Y[player - 1] - 1;
    for (int num = 0; num < 4; num++)
    {
        switch (dir)
        {
            case LEFT :
                _y--;
                        break;
            case RIGHT :
                _y++;
                        break;
            case UP :
                _x--;
                        break;
            case DOWN :
                _x++;
                        break;
            case LEFT_UP :
                _x--, _y--;
                        break;
            case RIGHT_DOWN :
                _x++, _y++;
                        break;
            case LEFT_DOWN :
                _x++, _y--;
                        break;
            case RIGHT_UP :
                _x--, _y++;
                        break;
            default :
                        break;
        }
        if ((_x < 0 || _x >= row) || (_y < 0 || _y >= col))
            break;
        if (board[_x][_y] == board[X[player - 1] - 1][Y[player - 1] - 1])
            count++;
        else
            break;
    }
    return count;
}

static int IsWin(int board[ROW][COL], int row, int col, int player)
{
    if (board[X[player - 1] - 1][Y[player - 1] - 1] == EMPTY)
        return NEXT;
    for (int i = 0; i < 8; i += 2)
    {
        int num = ChessCount(board, row, col, (enum Dir)i, player) + ChessCount(board, row, col, (enum Dir)(i + 1), player) + 1;
        if (num >= 5)
            return player;
    }
    if (Count == ROW * COL)
        return DRAW;
    return NEXT;
}

static void Over(int result)
{
    switch (result)
    {
        case PLAYER1WIN :
            printf("Player1:WIN\n");
            break;
        case PLAYER2WIN :
            printf("Player2:WIN\n");
            break;
        case DRAW :
            printf("DRAW\n");
            break;
        default :
            break;
    }
    if (ai != nullptr && result == PLAYER2WIN)
        printf("Congratulation!!!\nidiot AI beat you\n");
    delete ai;
    ai = nullptr;
}

void Game(void)
{
    AI::Menu(ai);
    for (int i = 0; i <= 100; i++)
    {
        ProcessBar(50, (double)i / 100).BarShow();
        usleep(50000);
    }
    
    int board[ROW][COL];
    InitBoard(board, ROW, COL);
    int result = 0;
    
    do
    {
        for (int player = 1 ; player <= 2 && result == NEXT; player++)
        {
            int tmp = PlayerMove(board, ROW, COL, player);
            result = IsWin(board, ROW, COL, player);
            ShowBoard(board, ROW, COL);
            player = tmp;
        }
    } while(result == NEXT);
    Over(result);
    
    for (int i = 0; i <= 100; i++)
    {
        ProcessBar(50, (double)i / 100).BarShow();
        usleep(50000);
    }
}

#undef __GAME_CPP__
